home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / egem / source / popup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  9.2 KB  |  437 lines

  1.  
  2. #include "proto.h"
  3.  
  4. static int        ob_next(OBJECT *,int);
  5. static void     ob_change(OBJECT *,int,int);
  6. static int         ob_find(OBJECT *,int,int);
  7. static int        do_popup(OBJECT *,boolean,int,int *);
  8.  
  9. #ifdef DEBUG
  10. extern void check_hotkeys(OBJECT *);
  11. #endif
  12.  
  13. static int ob_next(OBJECT *tree,int start)
  14. {
  15.     reg OBJECT *obj;
  16.     reg int i = start;
  17.  
  18.     if (start<tree->ob_head)
  19.         start=tree->ob_head;
  20.     do
  21.     {
  22.         obj = tree + i;
  23.         if ((obj->ob_state & DISABLED)==0 && (obj->ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  24.             return(i);
  25.         i = obj->ob_next;
  26.     }
  27.     while (i>=0);
  28.     return(FAIL);
  29. }
  30.  
  31. static void ob_change(OBJECT *tree,int obj,int newstate)
  32. {
  33.     reg OBJECT *ob = tree + obj;
  34.     int x,y;
  35.  
  36.     objc_offset(tree,obj,&x,&y);
  37.     objc_change(tree,obj,0,x,y,ob->ob_width,ob->ob_height,newstate,1);
  38. }
  39.  
  40. static int ob_find(OBJECT *tree,int x,int y)
  41. {
  42.     reg int pos = objc_find(tree,ROOT,1,x,y);
  43.  
  44.     if (pos>0 && ob_next(tree,pos)==pos)
  45.         return(pos);
  46.     else
  47.         return(FAIL);
  48. }
  49.  
  50. static int do_popup(OBJECT *menu,boolean wrap,int last,int *dc)
  51. {
  52.     reg int current,old = FAIL,ret = FAIL;
  53.  
  54.     EVENT events =
  55.     {
  56.         MU_BUTTON | MU_M1 | MU_M2 | MU_KEYBD,
  57.         1,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,
  58.         {0,0,0,0,0,0,0,0}
  59.     };
  60.  
  61.     _mouse_pos(&events.ev_mmox,&events.ev_mmoy);
  62.     if ((current = ob_find(menu,events.ev_mmox,events.ev_mmoy))<=0)
  63.         current = last;
  64.  
  65.     for (;;)
  66.     {
  67.         reg int mpos;
  68.  
  69.         if (current!=old)
  70.         {
  71.             if (old>0)
  72.                 ob_change(menu,old,menu[old].ob_state & (~SELECTED));
  73.             
  74.             if (current>0)
  75.                 ob_change(menu,current,menu[current].ob_state | SELECTED);
  76.  
  77.             old = current;
  78.         }
  79.  
  80.         if ((mpos = objc_find(menu,ROOT,1,events.ev_mmox,events.ev_mmoy)) < 0)
  81.         {
  82.             events.ev_mm1flags    = 0;
  83.             events.ev_mm1x        = menu->ob_x;
  84.             events.ev_mm1y        = menu->ob_y;
  85.             events.ev_mm1width    = menu->ob_width;
  86.             events.ev_mm1height    = menu->ob_height;
  87.             events.ev_mflags    &= ~MU_M2;
  88.         }
  89.         else
  90.         {
  91.             events.ev_mm1flags    = 1;
  92.             objc_offset(menu,mpos,&events.ev_mm1x,&events.ev_mm1y);
  93.             events.ev_mm1width    = menu[mpos].ob_width;
  94.             events.ev_mm1height    = menu[mpos].ob_height;
  95.             events.ev_mm2x        = events.ev_mmox;
  96.             events.ev_mm2y        = events.ev_mmoy;
  97.             events.ev_mflags    |= MU_M2;
  98.         }
  99.         
  100.         events.ev_mwich = Event_Multi(&events,0);
  101.         if (events.ev_mwich & MU_BUTTON)
  102.         {
  103.             if (!(events.ev_mmobutton & 1))
  104.             {
  105.                 ret = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  106.                 break;
  107.             }
  108.             else
  109.                 events.ev_mbstate = 0;
  110.         }
  111.  
  112.         if (events.ev_mwich & (MU_M1|MU_M2))
  113.         {
  114.             current = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  115.             
  116.             if (events.ev_mwich & MU_M2)
  117.             {
  118.                 events.ev_mm2x = events.ev_mmox;
  119.                 events.ev_mm2y = events.ev_mmoy;
  120.             }
  121.         }
  122.         
  123.         if (events.ev_mwich & MU_KEYBD)
  124.         {
  125.             int exitmode = FALSE;
  126.  
  127.             switch (events.ev_mkreturn & 0x00ff)
  128.             {
  129.             case 13:
  130.             case 32:
  131.                 ret = current;
  132.                 exitmode = TRUE;
  133.                 break;
  134.             case 27:
  135.                 ret = FAIL;
  136.                 exitmode = TRUE;
  137.             }
  138.  
  139.             if (exitmode==FALSE)
  140.             {
  141.                 switch (events.ev_mkreturn>>8)
  142.                 {
  143.                 case 97:
  144.                     ret = FAIL;
  145.                     exitmode = TRUE;
  146.                     break;
  147.                 case 71:
  148.                     if (events.ev_mmokstate & 3)
  149.                     {
  150.                         reg int j;
  151.     
  152.                         for (j=menu->ob_head;j<=menu->ob_tail;j++)
  153.                             if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  154.                                  current = j;
  155.                     }
  156.                     else
  157.                         current = ob_next(menu,menu->ob_head);
  158.                     break;
  159.                 case 75:
  160.                 case 72:
  161.                     {
  162.                         reg int j,temp = FAIL;
  163.  
  164.                         if (current>menu->ob_head)
  165.                         {
  166.                             for (j=menu->ob_head;j<current;j++)
  167.                                 if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  168.                                      temp = j;
  169.                         }
  170.  
  171.                         if (temp<0 && (wrap || current<0))
  172.                         {
  173.                             for (j=menu->ob_head;j<=menu->ob_tail;j++)
  174.                                 if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  175.                                      temp = j;
  176.                         }
  177.  
  178.                         if (temp>0)
  179.                             current = temp;
  180.                     }
  181.                     break;
  182.                 case 77:
  183.                 case 80:
  184.                     if (current<menu->ob_tail)
  185.                     {
  186.                         if (current<0)
  187.                             current = ob_next(menu,menu->ob_head);
  188.                         else
  189.                         {
  190.                             int temp = ob_next(menu,menu[current].ob_next);
  191.                             if (temp>0 && temp!=current)
  192.                                 current = temp;
  193.                             else
  194.                                 current = ob_next(menu,menu->ob_head);
  195.                         }
  196.                     }
  197.                     else if (wrap)
  198.                         current = ob_next(menu,menu->ob_head);
  199.                     break;
  200.                 default:
  201.                     {
  202.                         int obj;
  203.     
  204.                         if ((obj=_is_hotkey(menu,events.ev_mkreturn,events.ev_mmokstate))>0)
  205.                         {
  206.                             if ((menu[obj].ob_state & DISABLED)==0 && (menu[obj].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  207.                             {
  208.                                 if (old>0)
  209.                                     ob_change(menu,old,menu[old].ob_state & (~SELECTED));
  210.                                 ob_change(menu,obj,menu[obj].ob_state | SELECTED);
  211.                                 evnt_timer(150,0);
  212.     
  213.                                 exitmode = TRUE;
  214.                                 ret = obj;
  215.                             }
  216.                         }
  217.                     }
  218.                 }
  219.             }
  220.  
  221.             if (exitmode)
  222.                 break;
  223.         }
  224.     }
  225.  
  226.     if (ret>0)
  227.         *dc = (events.ev_mbreturn>=2 || (events.ev_mmokstate & 3));
  228.     return (ret);
  229. }
  230.  
  231. int Popup(POPUP *popup,int mode,int center,int x,int y,int *index,int select)
  232. {
  233.     reg DIAINFO *info = popup->p_info;
  234.     reg OBJECT *menu = popup->p_menu,*tree=(info!=NULL) ? info->di_tree : NULL;
  235.     reg int current = FAIL,exit = FAIL,object;
  236.     int dc = FALSE;
  237.  
  238.     graf_mouse(ARROW,NULL);
  239.  
  240.     if (tree!=NULL)
  241.     {
  242.         object = (mode & POPUP_CYCLE) ? popup->p_cycle : popup->p_parent;
  243.         if (object>0)
  244.             ob_draw_chg(info,object,NULL,tree[object].ob_state|SELECTED,FALSE);
  245.     }
  246.  
  247.     {
  248.         reg int i;
  249.  
  250.         for (i=menu->ob_head;i<=menu->ob_tail;i++)
  251.         {
  252.             if (menu[i].ob_flags & SELECTABLE)
  253.                 menu[i].ob_state &= ~SELECTED;
  254.  
  255.             if (!(menu[i].ob_flags & HIDETREE))
  256.             {
  257.                 if (i==select)
  258.                 {
  259.                     if (mode & POPUP_CHECK)
  260.                         menu[i].ob_state |= CHECKED;
  261.                     if (current>=0)
  262.                         menu[current].ob_state &= ~CHECKED;
  263.                     current=i;
  264.                 }
  265.                 else if (menu[i].ob_state & CHECKED)
  266.                 {
  267.                     if (!(mode & POPUP_CHECK) || current>=0)
  268.                         menu[i].ob_state &= ~CHECKED;
  269.                     else
  270.                         current = i;
  271.                 }
  272.             }
  273.         }
  274.     }
  275.  
  276.     if (!(mode & POPUP_CYCLE))
  277.     {
  278.         int sx,sy,sw = menu->ob_width>>1,sh = menu->ob_height>>1,dummy;
  279.         long mem = 0l;
  280.         MFDB dial;
  281.  
  282.         _mouse_pos(&sx,&sy);
  283.         if (tree!=NULL && popup->p_button>0)
  284.         {
  285.             int bx,by;
  286.             objc_offset(tree,popup->p_button,&bx,&by);
  287.             if (x<=0)
  288.                 x = bx;
  289.             if (y<=0)
  290.                 y = by;
  291.         }
  292.  
  293.         switch (center)
  294.         {
  295.         case CENTER:
  296.             {
  297.                 INFOVSCR *vscr;
  298.  
  299.                 form_center(menu,&dummy,&dummy,&dummy,&dummy);
  300.                 if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  301.                 {
  302.                     menu->ob_x = vscr->x + (vscr->w>>1) - sw;
  303.                     menu->ob_y = vscr->y + (vscr->h>>1) - sh;
  304.                 }
  305.             }
  306.             break;
  307.         case XYPOS:
  308.             menu->ob_x = x;
  309.             menu->ob_y = y;
  310.             break;
  311.         case MOUSEPOS:
  312.             menu->ob_x = sx - sw;
  313.             menu->ob_y = sy - sh;
  314.             break;
  315.         case XPOS:
  316.             menu->ob_x = x;
  317.             menu->ob_y = sy - sh;
  318.             break;
  319.         case YPOS:
  320.             menu->ob_x = sx - sw;
  321.             menu->ob_y = y;
  322.             break;
  323.         case OBJPOS:
  324.             menu->ob_x = x;
  325.             menu->ob_y = y;
  326.             if (current>=0)
  327.             {
  328.                 menu->ob_x -= menu[current].ob_x;
  329.                 menu->ob_y -= menu[current].ob_y;
  330.             }
  331.         }
  332.  
  333.         Min(&menu->ob_x,clip.v_x2 - menu->ob_width - 3);
  334.         Max(&menu->ob_x,clip.v_x1 + 3);
  335.         Min(&menu->ob_y,clip.v_y2 - menu->ob_height - 3);
  336.         Max(&menu->ob_y,clip.v_y1 + 3);
  337.  
  338.         sx = menu->ob_x - 3;
  339.         sy = menu->ob_y - 3;
  340.         sw = menu->ob_width + 6;
  341.         sh = menu->ob_height + 6;
  342.  
  343.         _beg_ctrl();
  344.         mfdb(&dial,NULL,sw,sh,0,planes);
  345.         
  346.         {
  347.             reg long len = mfdb_size(&dial);
  348.  
  349.             if ((long) Malloc(-1l)>(len+4096l))
  350.             {
  351.                 if ((mem = (long) Malloc(len+256l))>0l)
  352.                 {
  353.                     dial.fd_addr    = (int *) ((mem & 0xfffffffel) + 2);
  354.                     _bitblt(menu,&dial,TRUE);
  355.                     goto draw_popup;
  356.                 }
  357.             }
  358.         }
  359.  
  360.         form_dial(FMD_START,sx,sy,sw,sh,sx,sy,sw,sh);
  361.         
  362.         draw_popup:
  363.         objc_draw(menu,ROOT,MAX_DEPTH,sx,sy,sw,sh);
  364.  
  365.     #ifdef DEBUG
  366.         check_hotkeys(menu);
  367.     #endif
  368.  
  369.         exit = do_popup(menu,popup->p_wrap,current,&dc);
  370.  
  371.         if (mem)
  372.         {
  373.             _bitblt(menu,&dial,FALSE);
  374.             Mfree((void *) mem);
  375.         }
  376.         else
  377.             form_dial(FMD_FINISH,sx,sy,sw,sh,sx,sy,sw,sh);
  378.         _end_ctrl();
  379.     }
  380.     else
  381.     {
  382.         if (current<0 || current>=menu->ob_tail)
  383.             exit = ob_next(menu,menu->ob_head);
  384.         else
  385.         {
  386.             int temp = ob_next(menu,menu[current].ob_next);
  387.             exit = (temp>0) ? temp : ob_next(menu,menu->ob_head);
  388.         }
  389.         evnt_timer(50,0);
  390.     }
  391.  
  392.     if (tree!=NULL && object>0)
  393.         ob_draw_chg(info,object,NULL,tree[object].ob_state & (~SELECTED),FALSE);
  394.  
  395.     if (exit>0)
  396.     {
  397.         if (mode & POPUP_CHECK)
  398.         {
  399.             if (current>=0)
  400.                 menu[current].ob_state &= ~CHECKED;
  401.             menu[exit].ob_state |= CHECKED;
  402.         }
  403.  
  404.         if (tree!=NULL && popup->p_set && popup->p_button>0)
  405.         {
  406.             ob_set_text(tree,popup->p_button,ob_get_text(menu,exit,0));
  407.             ob_draw_chg(info,popup->p_button,NULL,FAIL,FALSE);
  408.             if (popup->p_cycle>0)
  409.                 ob_draw_chg(info,popup->p_cycle,NULL,FAIL,FALSE);
  410.         }
  411.  
  412.         if (index!=NULL)
  413.         {
  414.             reg int i = 1,radio = 0;
  415.  
  416.             do
  417.             {
  418.                 if ((menu[i].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  419.                 {
  420.                     if (i==exit)
  421.                     {
  422.                         *index = radio;
  423.                         break;
  424.                     }
  425.                     radio++;
  426.                 }
  427.                 i = menu[i].ob_next;
  428.             } while (i>=0);
  429.         }
  430.     }
  431.  
  432.     if (exit<=0)
  433.         return(0);
  434.     else
  435.         return ((dc) ? (exit|0x8000) : exit);
  436. }
  437.